﻿#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <new>		// for std::bad_alloc
#include <memory>
#include <atomic>
#include <mutex>
#include <thread>
#include <cassert>
#include <string>
#include <map>
#include <unordered_map>
#include <functional>
using namespace std;

template <class T>
class SmartPtr
{
public:
	// RAII
	SmartPtr(T* ptr)
		: _ptr(ptr)
	{}

	// 重载运算符，模拟指针的⾏为，⽅便访问资源
	T* operator->()
	{
		return _ptr;
	}

	T& operator*()
	{
		return *_ptr;
	}

	T& operator[](size_t i)
	{
		return _ptr[i];
	}

	~SmartPtr()
	{
		cout << "delete[] " << _ptr << endl;
		delete[] _ptr;
		_ptr = nullptr;
	}

private:
	T* _ptr;
};

double Divide(double a, double b)
{
	if (0 == b)
	{
		throw "Division by zero condition!";
	}

	return a / b;
}

void Func1()
{
	int* arr1 = nullptr, * arr2 = nullptr;

	try
	{
		arr1 = new int[10];
		arr2 = new int[10];

		double a = 0.0, b = 0.0;
		cin >> a >> b;

		cout << Divide(a, b) << endl;

		cout << "delete[] " << (void*)arr1 << endl;
		cout << "delete[] " << (void*)arr2 << endl;

		delete[] arr1;
		arr1 = nullptr;
		delete[] arr2;
		arr2 = nullptr;
	}
	catch (...)
	{
		if (arr1)
		{
			cout << "delete[] " << (void*)arr1 << endl;
			delete[] arr1;
			arr1 = nullptr;
		}

		if (arr2)
		{
			cout << "delete[] " << (void*)arr2 << endl;
			delete[] arr2;
			arr2 = nullptr;
		}
		
		throw;
	}
}

void Func2()
{
	SmartPtr<int> sp1 = new int[10];
	SmartPtr<int> sp2 = new int[10];

	for (size_t i = 0; i < 10; ++i)
	{
		sp1[i] = sp2[i] = i;
	}

	double a = 0.0, b = 0.0;
	cin >> a >> b;

	cout << Divide(a, b) << endl;
}

void Test1()
{
	try
	{
		//Func1();
		Func2();
	}
	catch (const char* const& errmsg) // catch (const char* errmsg)
	{
		cout << "【" << errmsg << "】" << endl;
	}
	catch (const bad_alloc& e)
	{
		cout << "【" << "Allocation failed: " << e.what() << "】" << endl;
	}
	catch (...)
	{
		cout << "【" << "Unknown Exception" << "】"<< endl;
	}
}

struct Date
{
	Date(int year = 1970, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}

	void getDate() const
	{
		if (this)
			cout << _year << "-" << _month << "-" << _day << endl;
		else
			cout << "空操作，不对空指针解引用" << endl;
	}

	~Date()
	{
		cout << "~Date" << endl;
		_year = 0;
		_month = 0;
		_day = 0;
	}

	int _year;
	int _month;
	int _day;
};

void Test2()
{
	auto_ptr<Date> ap1(new Date);
	auto_ptr<Date> ap2(ap1);		// 拷贝时转移资源管理权，被拷贝对象ap1悬空

	//ap1->_year;					// 空指针访问，ap1对象已悬空

	unique_ptr<Date> up1(new Date);
	//unique_ptr<Date> up2(up1);	// 不支持拷贝【err 尝试引用已删除的函数】
	unique_ptr<Date> up3(move(up1));// 支持移动。移动后up1悬空，使用移动要谨慎

	shared_ptr<Date> sp1(new Date);
	shared_ptr<Date> sp2(sp1);		// 支持拷贝
	shared_ptr<Date> sp3(sp2);		// sp1、sp2、sp3管理同一个资源（Date对象）

	cout << sp1.use_count() << "\t" << sp2.use_count() << "\t" << sp3.use_count() << endl << endl;// 调用成员函数。返回引用同一管理对象的shared_ptr的对象个数

	cout << sp1->_year << "\t" << sp2->_year << "\t" << sp3->_year << endl;
	++sp3->_year;
	cout << sp1->_year << "\t" << sp2->_year << "\t" << sp3->_year << endl;

	shared_ptr<Date> sp4(move(sp1));// ⽀持移动。移动后sp1悬空，使⽤移动要谨慎
	cout << sp4.use_count() << endl;
	cout << "<<<<<<<<<<<<<<<<<<<<" << endl << endl;
}

template <class T>
void FunctionDeleter(T* p)
{
	delete[] p;
	p = nullptr;
}

template <class T>
struct FunctorDeleter
{
	void operator()(T* p)
	{
		delete[] p;
		p = nullptr;
	}
};

auto LambdaDeleter = [](Date* p)
{
	delete[] p;
	p = nullptr;
};

class Fclose
{
public:
	void operator()(FILE* pf)
	{
		cout << "fclose: " << pf << endl;

		fclose(pf);
		pf = nullptr;
	}
};

void Test3()
{
	// 运行时导致程序崩溃，new[]申请的资源必须使用delete[]释放
	/*unique_ptr<Date> up1(new Date[10]);
	shared_ptr<Date> sp1(new Date[10]);*/

	// unique_ptr和shared_ptr从C++17开始同时支持对数组资源的管理
	unique_ptr<Date[]> up1(new Date[2]);							// unique_ptr特化版本析构时自动使用delete[]
	unique_ptr<Date[]> up2(new Date[2], default_delete<Date[]>());	// 显式传入删除器
	shared_ptr<Date[]> sp1(new Date[2]);							// std::default_delete的特化版本支持数组资源的析构
	shared_ptr<Date[]> sp2(new Date[2], default_delete<Date[]>());	// 显式传入删除器

	{
		// 显式传入删除器
		unique_ptr<Date[], void(*)(Date*)> up1(new Date[2], FunctionDeleter<Date>);			// 函数
		shared_ptr<Date[]> sp1(new Date[2], FunctionDeleter<Date>);

		unique_ptr<Date[], FunctorDeleter<Date>> up2(new Date[2], FunctorDeleter<Date>());	// 仿函数
		shared_ptr<Date[]> sp2(new Date[2], FunctorDeleter<Date>());

		unique_ptr<Date[], decltype(LambdaDeleter)> up3(new Date[2], LambdaDeleter);		// lambda表达式
		shared_ptr<Date[]> sp3(new Date[2], [](Date* p){					
				delete[] p;
				p = nullptr;
			});

		unique_ptr<FILE, Fclose> up4(fopen("Test.cpp", "r"), Fclose());						// 其它类型如文件资源的管理
		shared_ptr<FILE> sp4(fopen("Test.cpp", "r"), [](FILE* pf){
			cout << "fclose: " << pf << endl;

			fclose(pf);
			pf = nullptr;
		});
	}
	cout << "*******************" << endl;

	{
		shared_ptr<Date> sp1(new Date(2025, 1, 1));
		shared_ptr<Date> sp2 = make_shared<Date>(2025, 1, 2);
		auto sp3 = make_shared<Date>(2025, 1, 3);
		shared_ptr<Date> sp4;

		if (sp1)
			cout << "sp1 is not nullptr" << endl;
		
		if (!sp4)
			cout << "sp4 is nullptr" << endl;
	}
	cout << "*******************" << endl;

	// err
	//unique_ptr<Date> sp6 = new Date(2024, 9, 11);
	//shared_ptr<Date> sp5 = new Date(2024, 9, 11);
}

namespace yyp
{
	template <class T>
	class auto_ptr
	{
	public:
		explicit auto_ptr(T* ptr = nullptr)
			: _ptr(ptr)
		{}

		// 管理权转移
		auto_ptr(auto_ptr& ap)
			: _ptr(ap._ptr)
		{
			ap._ptr = nullptr;
		}

		auto_ptr& operator=(const auto_ptr& ap)
		{
			if (this != &ap)
			{
				if (_ptr)
					delete _ptr;	// 释放当前对象中资源


				_ptr = ap._ptr;		// 转移资源
				ap._ptr = nullptr;
			}

			return *this;
		}

		T* get() const
		{
			return _ptr;
		}

		// 像指针⼀样使⽤
		T& operator*() const
		{
			if (!_ptr)
				assert(false);

			return *_ptr;
		}

		T* operator->() const
		{
			if (!_ptr)
				assert(false);

			return _ptr;
		}

		~auto_ptr()
		{
			if (_ptr)
			{
				cout << "auto_ptr delete: " << _ptr << endl;
				delete _ptr;
				_ptr = nullptr;
			}
		}

	private:
		T* _ptr;
	};

	template <class T>
	class unique_ptr
	{
	public:
		explicit unique_ptr(T* ptr = nullptr)
			: _ptr(ptr)
		{}

		unique_ptr(const unique_ptr& up) = delete;
		unique_ptr operator=(const unique_ptr& up) = delete;

		unique_ptr(unique_ptr&& up) noexcept
			: _ptr(up._ptr)
		{
			up._ptr = nullptr;
		}

		unique_ptr& operator=(unique_ptr&& up)
		{
			if (_ptr)
				delete _ptr;

			_ptr = up._ptr;
			up._ptr = nullptr;

			return *this;
		}

		T* get() const
		{
			return _ptr;
		}

		// 像指针⼀样使⽤
		T& operator*() const
		{
			if (!_ptr)
				assert(false);

			return *_ptr;
		}

		T* operator->() const
		{
			if (!_ptr)
				assert(false);

			return _ptr;
		}

		~unique_ptr()
		{
			if (_ptr)
			{
				cout << "unique_ptr delete: " << _ptr << endl;
				delete _ptr;
				_ptr = nullptr;
			}
		}

	private:
		T* _ptr;
	};

	template <class T>
	class shared_ptr
	{
	public:
		explicit shared_ptr(T* ptr = nullptr)
			: _ptr(ptr)
			, _pcount(new atomic<int>(1))
		{}
		
		// 1、类模板与成员函数模板的同名模板参数（如均用T）会因作用域嵌套发生名称遮蔽，编译器会将其识别为两个完全独立的类型参数。建议使用不同命名，显式指明这两个模板参数可以是不同类型
		// 实际使用中实例化的模板函数，二者的实际类型要么相同，要么是（类模板）基类和（成员函数模板）派生类的关系，都可以执行_ptr(ptr)的赋值操作
		// 2、可以将模板参数简化为一个。此时可以直接使用类模板的T参数 template <class D>
		//template <class T, class D>
		template <class U, class D>
		shared_ptr(U* ptr, D del)
			: _ptr(ptr)
			, _pcount(new atomic<int>(1))
			, _del(del)
		{}

		shared_ptr(const shared_ptr& sp)
		{
			std::unique_lock<std::mutex> lk(_mtx);

			// 避免sp被并发修改
			_ptr = sp._ptr;
			_pcount = sp._pcount;
			_del = sp._del;

			if (_pcount)
				++(*_pcount);
		}

		shared_ptr(shared_ptr&& sp)
		{
			std::unique_lock<std::mutex> lk(_mtx);

			_ptr = sp._ptr;
			_pcount = sp._pcount;
			_del = sp._del;

			sp._ptr = nullptr;
			sp._pcount = nullptr;
			sp._del = nullptr;
		}

		shared_ptr& operator=(const shared_ptr& sp)
		{
			std::unique_lock<std::mutex> lk(_mtx);

			//if (this != &sp)
			if (_ptr != sp._ptr)
			{
				release();

				_ptr = sp._ptr;
				_pcount = sp._pcount;
				++(*_pcount);
				_del = sp._del;
			}

			return *this;
		}

		shared_ptr& operator=(shared_ptr&& sp)
		{
			std::unique_lock<std::mutex> lk(_mtx);

			if (_ptr != sp._ptr)
			{
				release();

				_ptr = sp._ptr;
				_pcount = sp._pcount;
				++(*_pcount);
				_del = move(sp._del); // 移动删除器（function支持移动，更高效）
			}

			return *this;
		}

		void release()
		{
			if (_pcount && 0 == --(*_pcount))
			{
				// 最后⼀个管理资源的对象析构时，释放其管理的资源
				_del(_ptr);
				delete _pcount;
				_ptr = nullptr;
				_pcount = nullptr;
			}
		}

		T& operator*() const
		{
			if (!_ptr)
				assert(false);

			return *_ptr;
		}

		T* operator->() const
		{
			if (!_ptr)
				assert(false);

			return _ptr;
		}

		int use_count() const
		{
			// 返回0仅表示不持有资源的空实例
			return _pcount ? _pcount->load() : 0;
		}

		T* get() const
		{
			return _ptr;
		}

		~shared_ptr()
		{
			// 备份当前计数，防止读取打印的过程中，被其它线程修改数据
			int cur_count = _pcount ? _pcount->load() : 0;
			bool will_release = (_pcount && 1 == cur_count);

			unique_lock<mutex> lk(_mtx);
			cout << "shared_ptr delete: ";
			if (!_ptr)
			{
				cout << "空对象";
			}
			else
			{
				// 三目运算符 a ? b : c 要求 b 和 c 的类型必须可兼容，即能通过隐式转换统一为同一类型。b和c类型一致是可兼容的特例
				cout << "引用计数 " << cur_count;
				//cout << "引用计数 " << (_pcount ? static_cast<int>(*_pcount) : 0);
				if (will_release)
					cout << " ，释放管理的资源 " << _ptr;
			}
			cout << endl;
			
			release();
		}

	private:
		T* _ptr;
		//int* _pcount;
		atomic<int>* _pcount;	// 原子类型，线程安全
		static mutex _mtx;

		function<void(T*)> _del = [](T* ptr) {
			delete ptr;
			ptr = nullptr;
		};
	};
	template <class T>
	mutex shared_ptr<T>::_mtx;

	template <class T>
	class weak_ptr
	{
	public:
		weak_ptr()
		{}

		weak_ptr(const shared_ptr<T>& sp)
			: _ptr(sp.get())
		{}

		weak_ptr& operator=(const shared_ptr<T>& sp)
		{
			_ptr = sp.get();

			return *this;
		}

	private:
		T* _ptr = nullptr;
	};

	void Test4()
	{
		auto_ptr<Date> ap1(new Date);
		auto_ptr<Date> ap2(ap1);		// ap1被悬空

		//ap1->_year;					// 空指针访问，ap1已悬空

		unique_ptr<Date> up1(new Date);
		//unique_ptr<Date> up2(up1);	// 不支持拷贝
		unique_ptr<Date> up3(move(up1));// 支持移动

		shared_ptr<Date> sp1(new Date);
		shared_ptr<Date> sp2(sp1);		// 支持拷贝
		shared_ptr<Date> sp3(sp2);		// sp1、sp2、sp3管理同一个资源

		cout << "auto_ptr  : " << ap1.get() << "\t" << ap2.get() << endl;
		cout << "unique_ptr: " << up1.get() << "\t" << up3.get() << endl;
		cout << "shared_ptr: " << sp1.get() << "\t" << sp2.get() << "\t" << sp3.get() << endl << endl;

		cout << sp1.use_count() << "\t" << sp2.use_count() << "\t" << sp3.use_count() << endl << endl;

		cout << sp1->_year << "\t" << sp2->_year << "\t" << sp3->_year << endl;
		++sp3->_year;
		cout << sp1->_year << "\t" << sp2->_year << "\t" << sp3->_year << endl << endl;

		shared_ptr<Date> sp4(move(sp1));// ⽀持移动
		cout << sp4.use_count() << endl << endl;
	}
}

//void Test5()
//{
//	struct B;
//
//	struct A
//	{
//		shared_ptr<B> _a;
//		//weak_ptr<B> _a;	//不增加引用计数
//
//		~A()
//		{
//			cout << "A销毁" << endl;
//		}
//	};
//
//	struct B
//	{
//		shared_ptr<A> _b;
//		//weak_ptr<A> _b;	// 不增加引用计数
//
//		~B()
//		{
//			cout << "B销毁" << endl;
//		}
//	};
//
//	{
//		shared_ptr<A> a(new A());
//		shared_ptr<B> b(new B());
//
//		cout << a.use_count() << " " << b.use_count() << endl;
//		a->_a = b;
//		b->_b = a;
//		cout << a.use_count() << " " << b.use_count() << endl;
//	}
//}

void Test5()
{
	struct ListNode
	{
		int _data = 0;
		//shared_ptr<ListNode> _prev;
		weak_ptr<ListNode> _prev;
		shared_ptr<ListNode> _next;

		~ListNode()
		{
			cout << "~ListNode" << endl;
		}
	};

	{
		shared_ptr<ListNode> n1 = make_shared<ListNode>();
		shared_ptr<ListNode> n2{ make_shared<ListNode>() };

		cout << n1.use_count() << " " << n2.use_count() << endl;
		n1->_next = n2;
		n2->_prev = n1;
		cout << n1.use_count() << " " << n2.use_count() << endl;
	}
}

void Test6()
{
	std::shared_ptr<string> sp1(new string("000"));
	std::shared_ptr<string> sp2(sp1);
	std::weak_ptr<string> wp = sp1;

	cout << wp.expired() << " " << wp.use_count() << endl;

	sp1 = make_shared<string>("111");						// sp1指向新资源"111"
	cout << wp.expired() << " " << wp.use_count() << endl;

	sp2 = make_shared<string>("222");						// sp2指向新资源"222"，持有"000"的引用计数从1减为0（"000"被释放），wp原关联的"000"失效
	cout << wp.expired() << " " << wp.use_count() << endl;

	wp = sp1;												// wp指向新资源"111"
	//std::shared_ptr<string> sp3 = wp.lock();
	auto sp3 = wp.lock();									// 构造新的shared_ptr，指向资源"111"
	cout << wp.expired() << " " << wp.use_count() << endl;

	*sp3 += "333";
	cout << *sp1 << endl;
}

void Test7()
{
	struct A
	{
		int _a = 0;
		int _b = 0;

		~A()
		{
			cout << "~A" << endl;
		}
	};

	mutex Mutex;
	const size_t N = 3;
	yyp::shared_ptr<A> sp(new A());

	auto f = [&] 
	{
		for (size_t i = 0; i < N; ++i)
		{
			yyp::shared_ptr<A> copy(sp);

			{
				unique_lock<mutex> lk(Mutex);
				++copy->_a;
				++copy->_b;
			}
		}
	};

	thread t1(f);
	thread t2(f);

	t1.join();
	t2.join();

	cout << "\n************" << endl;
	cout << sp.use_count() << endl;
	cout << sp->_a << " " << sp->_b << endl;
	cout << "************" << endl << endl;
}

void Test8()
{
	// 申请⼀个1G未释放，这个程序多次运⾏也没啥危害
	// 因为程序⻢上就结束，进程结束各种资源也就回收了
	char* ptr = new char[1024 * 1024 * 1024];
	cout << (void*)ptr << endl;
}

void Test9()
{
	map<string, int> s1;
	unordered_map<string, int> s2;
	int a[] = {3, 1, 6, 7, 8, 2, 1, 1, 5, 6, 7, 6};

	for (auto it = a; it != a+sizeof(a)/sizeof(int); ++it)
	{
		s1.insert({ to_string(*it), *it });
		s2.insert({ to_string(*it), *it });
	}
	

	for (auto it = s1.begin(); it != s1.end(); ++it)
	{
		cout << it->first << ":" << it->second << "\t";
	}
	cout << endl;

	for (auto it = s2.begin(); it != s2.end(); ++it)
	{
		cout << it->first << ":" << it->second << "\t";
	}
	cout << endl;
}

int main()
{
	//Test1();
	//Test2();
	//Test3();
	//yyp::Test4();
	//Test5();
	//Test6();
	//Test7();
	//Test8();
	Test9();

	return 0;
}